package com.ruyuan.realm;

//import com.ruyuan.authenticate.MySimpleByteSource;
import com.ruyuan.authenticate.MySimpleByteSource;
import com.ruyuan.repository.bean.User;
import com.ruyuan.service.RolePermissionService;
import com.ruyuan.service.UserRoleService;
import com.ruyuan.service.UserService;
import com.ruyuan.token.TokenUtil;
import com.ruyuan.token.TokenUtilAware;
import com.ruyuan.token.UsernamePasswordTypeToken;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @author xx
 */
@Component
public class MyRealm extends AuthorizingRealm implements TokenUtilAware {

    @Autowired
    private UserService userService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RolePermissionService rolePermissionService;

    private TokenUtil util;

    public MyRealm() {
        this.setAuthenticationCachingEnabled(true);
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        String userName = (String) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        List<String> roles = userRoleService.queryRolesByUserName(userName);
        info.setRoles(new HashSet<>(roles));
        Set<String> permissions = new HashSet<>();
        for (String role : info.getRoles()) {
            List<String> permissionList = rolePermissionService.queryPermissionsByRole(role);
            if (!CollectionUtils.isEmpty(permissionList)) {
                permissions.addAll(new HashSet<>(permissionList));
            }
        }
        info.setStringPermissions(permissions);
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName = (String) token.getPrincipal();
        User user = userService.queryByUserName(userName);
        if (user == null) {
            throw new UnknownAccountException("user not exists");
        }
        MySimpleByteSource bytes = new MySimpleByteSource(userName);
//        ByteSource bytes = ByteSource.Util.bytes(userName);
        return new SimpleAuthenticationInfo(userName, user.getPassword(), bytes, getName());
    }

    @Override
    public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(1024);
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        super.setCredentialsMatcher(hashedCredentialsMatcher);
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordTypeToken;
//        return util.supports(token, this);
    }

    @Override
    public String getName() {
        return "myRealm";
    }

    @Override
    public void setTokenUtil(TokenUtil tokenUtil) {
        this.util = tokenUtil;
    }
}
